package ltd.sshine.networkclient.handler;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import lombok.extern.slf4j.Slf4j;
import ltd.sshine.networkclient.config.ClientConfig;
import ltd.sshine.networkclient.config.ServerConfig;
import ltd.sshine.networkclient.service.ProxyService;
import ltd.sshine.networkcommon.pojo.Result;
import ltd.sshine.networkcommon.vo.ConnectionVO;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

@Slf4j
public class ClientAuthChannelHandler extends ChannelInboundHandlerAdapter {

    private final ChannelHandler[] authUseHandler;

    private final ObjectMapper objectMapper;
    private final ServerConfig serverConfig;
    private final ClientConfig clientConfig;
    private final ProxyService proxyService;

    public ClientAuthChannelHandler(ObjectMapper objectMapper,
                                    ServerConfig serverConfig,
                                    ClientConfig clientConfig,
                                    ProxyService proxyService, ChannelHandler... authUseHandler) {
        this.objectMapper = objectMapper;
        this.serverConfig = serverConfig;
        this.clientConfig = clientConfig;
        this.proxyService = proxyService;
        this.authUseHandler = authUseHandler;

    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String s = ((ByteBuf) msg).toString(StandardCharsets.UTF_8);
        log.debug("{}", s);
        Result<ConnectionVO> config = objectMapper.readValue(s, new TypeReference<>() {
        });
        if (config.getCode() == 200) {

            log.info(
                    """
                            \n已开启代理
                            服务器地址：http://{}:{}
                            本地代理地址：http://{}:{}""", serverConfig.getHost(), config.getData().getPort(),
                    clientConfig.getHost(), clientConfig.getPort());
        } else {
            log.error("{}", config.getMsg());
            ctx.close();
            return;
        }
        buildNewChannel(ctx, clientConfig.getHost(), clientConfig.getPort());
    }

    private void buildNewChannel(ChannelHandlerContext ctx, String host, int port) {
        ctx.pipeline().addLast(
                new HttpServerCodec(),
                new HttpObjectAggregator(1024 * 1024 * 1024),
                new HttpClientCodec(),
                new HttpProxyChannelHandler(host, port, proxyService)
        );
        Arrays.stream(authUseHandler).forEach(ctx.pipeline()::remove);
        ctx.pipeline().remove(this);
    }


}
